#ifndef CONCURENTQUEUE_H
#define CONCURENTQUEUE_H

//thread safe queue

#include <queue>

#include <boost/thread.hpp>

template<typename Data>
class ConcurrentQueue
{
private:
    std::queue<Data> m_queue;
    mutable boost::mutex m_mutex;
    boost::condition_variable m_conditionVariable;
public:
    //init queue, thread unsafe!
    ConcurrentQueue(const std::queue<Data> & queue) :
        m_queue(queue) {}
    ConcurrentQueue(){}

    void push(Data const& data)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        m_queue.push(data);
        lock.unlock();
        m_conditionVariable.notify_one();
    }    

    bool empty() const
    {
        boost::mutex::scoped_lock lock(m_mutex);
        return m_queue.empty();
    }

    bool size() const
    {
        boost::mutex::scoped_lock lock(m_mutex);
        return m_queue.size();
    }

    bool try_pop(Data& data)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        if(m_queue.empty())
            return false;
        data = m_queue.front();
        m_queue.pop();
        return true;
    }

    void lock_and_pop(Data& data)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        while(m_queue.empty())
            m_conditionVariable.wait(lock);
        data = m_queue.front();
        m_queue.pop();
    }

    //not tested!
    bool wait_and_pop(Data& data, boost::system_time const & abs_time)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        if(!m_conditionVariable.timed_wait(lock, abs_time) || m_queue.empty())
            return false;
        data = m_queue.front();
        m_queue.pop();
        return true;
    }
};

#endif // CONCURENTQUEUE_H
